﻿#If NETFX_CORE Then
Imports Windows.Storage
#Else
Imports System.Threading.Tasks
#End If
Imports System.IO.IsolatedStorage
Imports System.Runtime.CompilerServices
Imports System.IO
Imports Runa.Common.Helper

Namespace Global.System.IO

    Public Module Extension

#If (Not NETFX_CORE) And (Not WINDOWS_PHONE) And (Not SILVERLIGHT) Then

        <Extension()> _
        Public Sub CopyTo(ByVal di As DirectoryInfo, ByVal dst As String, Optional ByVal isOverrite As Boolean = False)
            My.Computer.FileSystem.CopyDirectory(di.FullName, dst, isOverrite)
        End Sub

        <Extension()> _
        Public Function GetStreamMd5Hash(ByVal inputStream As Stream) As String
            Dim strResult As String = ""
            Dim strHashData As String = ""
            Dim arrbytHashValue As Byte()
            Dim MD5Hasher As New System.Security.Cryptography.MD5CryptoServiceProvider()
            Try
                arrbytHashValue = MD5Hasher.ComputeHash(inputStream)
                inputStream.Close()
                strHashData = System.BitConverter.ToString(arrbytHashValue)
                strHashData = strHashData.Replace("-", "")
                strResult = strHashData
            Catch ex As System.Exception
                Throw ex
            End Try
            Return strResult
        End Function

        <Extension()> _
        Public Sub CopyTo(ByRef [Me] As DirectoryInfo, ByVal dst As String)
            Dim s = [Me]
            Dim d As New DirectoryInfo(dst)
            If s.FullName = d.FullName Then
                Return
            Else
                If Not d.Exists Then d.Create()
                Dim files = s.GetFiles()
                For Each file As FileInfo In files
                    file.CopyTo(Path.Combine(d.FullName, file.Name), True)
                Next file
                Dim dirs = s.GetDirectories()
                For Each [dir] As DirectoryInfo In dirs
                    Dim dst_dir = Path.Combine(d.FullName, dir.Name)
                    dir.CopyTo(dst_dir)
                Next [dir]
            End If
        End Sub

        <Extension()> _
        Public Function GetMd5Hash(ByVal [Me] As FileInfo) As String
            Dim pathName As String = [Me].FullName
            Dim strResult As String = ""
            Dim strHashData As String = ""
            Dim arrbytHashValue As Byte()
            Dim fs As System.IO.FileStream = Nothing
            Dim MD5Hasher As New System.Security.Cryptography.MD5CryptoServiceProvider()
            Try
                fs = New System.IO.FileStream(pathName.Replace("""", ""), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite)
                arrbytHashValue = MD5Hasher.ComputeHash(fs)
                fs.Close()
                strHashData = System.BitConverter.ToString(arrbytHashValue)
                strHashData = strHashData.Replace("-", "")
                strResult = strHashData
            Catch ex As System.Exception
                Throw ex
            End Try
            Return strResult
        End Function

        <Extension()> _
        Public Sub ParallelForEach(ByVal [Me] As DirectoryInfo, ByVal act As System.Action(Of FileInfo), ByVal ParamArray exts() As String)
            If [Me].Exists = True Then
                Dim targetFiles As New List(Of FileInfo)
                For Each item In exts
                    targetFiles.AddRange([Me].EnumerateFiles("*" & item))
                Next
                Parallel.ForEach(targetFiles,
                    Sub(item)
                        Call act(item)
                    End Sub)
                Dim dirs = [Me].GetDirectories()
                For Each item In dirs
                    ParallelForEach(item, act, exts)
                Next
            End If
        End Sub

        <Extension()> _
        Public Sub ForEach(ByVal [Me] As DirectoryInfo, ByVal act As System.Action(Of FileInfo), ByVal ParamArray exts() As String)
            If [Me].Exists = True Then
                Dim targetFiles As New List(Of FileInfo)
                If exts.Length > 0 Then
                    For Each item In exts
                        targetFiles.AddRange([Me].EnumerateFiles("*" & item))
                    Next
                Else
                    targetFiles.AddRange([Me].EnumerateFiles())
                End If
                For Each item In targetFiles
                    Call act(item)
                Next
                Dim dirs = [Me].GetDirectories()
                For Each item In dirs
                    ForEach(item, act, exts)
                Next
            End If
        End Sub

#Else
#If WINDOWS_PHONE Then

#ElseIf SILVERLIGHT Then

#Else

        <Extension()> _
        Public Function ToFileAccessMode(ByVal fileMode As FileMode) As FileAccessMode
            Return FileAccessMode.ReadWrite
        End Function

        <Extension()> _
        Public Sub CopyTo(ByVal di As StorageFolder, ByVal dst As String, Optional ByVal isOverrite As Boolean = False)
            Dim dstFolder = StorageFolder.GetFolderFromPathAsync(dst).AsTask().Result
            Dim dstFiles = dstFolder.GetFilesAsync().AsTask().Result
            Dim dirs = di.GetFoldersAsync().AsTask().Result
            Dim files = di.GetFilesAsync().AsTask().Result
            For Each file In files
                If dstFiles.Contains(Function(item) item.Name.ToLower() = file.Name.ToLower()) Then
                    If isOverrite = False Then
                        Continue For
                    End If
                End If
                Dim r = file.CopyAsync(dstFolder).AsTask().Result
            Next
            For Each dir In dirs
                dir.CopyTo(Path.Combine(dst, dir.Name), isOverrite)
            Next
        End Sub

        <Extension()> _
        Public Async Function CopyToAsync(ByVal di As StorageFolder, ByVal dst As String, Optional ByVal isOverrite As Boolean = False) As Task
            Dim dstFolder = Await StorageFolder.GetFolderFromPathAsync(dst)
            Dim dstFiles = Await dstFolder.GetFilesAsync()
            Dim dirs = Await di.GetFoldersAsync()
            Dim files = Await di.GetFilesAsync()
            For Each file In files
                If dstFiles.Contains(Function(item) item.Name.ToLower() = file.Name.ToLower()) Then
                    If isOverrite = False Then
                        Continue For
                    End If
                End If
                Await file.CopyAsync(dstFolder)
            Next
            For Each dir In dirs
                Await dir.CopyToAsync(Path.Combine(dst, dir.Name), isOverrite)
            Next
        End Function

        <Extension()> _
        Public Sub CopyTo(ByVal di As StorageFolder, ByVal dst As String, ByVal ifs As IsolatedStorageFile, Optional ByVal isOverrite As Boolean = False)
            Dim dstFolder = ifs.GetDirectory(dst)
            Dim dstFiles = dstFolder.GetFilesAsync().AsTask().Result
            Dim dirs = di.GetFoldersAsync().AsTask().Result
            Dim files = di.GetFilesAsync().AsTask().Result
            For Each file In files
                If dstFiles.Contains(Function(item) item.Name.ToLower() = file.Name.ToLower()) Then
                    If isOverrite = False Then
                        Continue For
                    End If
                End If
                Dim r = file.CopyAsync(dstFolder).AsTask().Result
            Next
            For Each dir In dirs
                dir.CopyTo(Path.Combine(dst, dir.Name))
            Next
        End Sub

        <Extension()> _
        Public Async Function CopyToAsync(ByVal di As StorageFolder, ByVal dst As String, ByVal ifs As IsolatedStorageFile, Optional ByVal isOverrite As Boolean = False) As Task
            Dim dstFolder = ifs.GetDirectory(dst)
            Dim dstFiles = Await dstFolder.GetFilesAsync()
            Dim dirs = Await di.GetFoldersAsync()
            Dim files = Await di.GetFilesAsync()
            For Each file In files
                If dstFiles.Contains(Function(item) item.Name.ToLower() = file.Name.ToLower()) Then
                    If isOverrite = False Then
                        Continue For
                    End If
                End If
                Await file.CopyAsync(dstFolder)
            Next
            For Each dir In dirs
                Await dir.CopyToAsync(Path.Combine(dst, dir.Name), isOverrite)
            Next
        End Function

        <Extension()> _
        Public Sub Close(ByVal [Me] As Stream)
            Return
        End Sub

        <Extension()> _
        Public Sub Close(ByVal [Me] As BinaryReader)
            Return
        End Sub

        <Extension()> _
        Public Sub Close(ByVal [Me] As BinaryWriter)
            Return
        End Sub

        <Extension()> _
        Public Sub Close(ByVal [Me] As StreamReader)
            Return
        End Sub

        <Extension()> _
        Public Sub Close(ByVal [Me] As TextReader)
            Return
        End Sub

#End If
#End If

    End Module

End Namespace